﻿using AutoMapper;
using King.Box.Models.Db.Sys;
using King.Box.Models.Util;
using King.Box.Models.View.Sys;
using King.Box.Utils.Global;
using King.Box.Utils.Utils;
using PsCat.Aspet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace King.Box.Service.Impl
{
    public class HomeService : IHomeService
    {
        private readonly ISafetyService _safetyService;
        private readonly ISysService _sysService;
        private readonly IDataService<Sys_User> _sysUserService;
        private readonly IDataService<Sys_Role> _sysRoleService;
        private readonly IDataService<Sys_Menu> _sysMenuService;
        private readonly IDataService<Sys_User_Role> _sysUserRoleService;
        private readonly IDataService<Sys_Permission> _sysPermissionService;
        private readonly IDataService<Sys_Role_Permission> _sysRolePermissionService;

        public HomeService(ISysService sysService, IDataService<Sys_User> sysUserService, IDataService<Sys_User_Role> sysUserRoleService, IDataService<Sys_Role_Permission> sysRolePermissionService,
           IDataService<Sys_Permission> sysPermissionService, IDataService<Sys_Role> sysRoleService, IDataService<Sys_Menu> sysMenuService, ISafetyService safetyService)
        {
            _sysRolePermissionService = sysRolePermissionService;
            _sysPermissionService = sysPermissionService;
            _sysUserRoleService = sysUserRoleService;
            _sysMenuService = sysMenuService;
            _sysRoleService = sysRoleService;
            _sysUserService = sysUserService;
            _safetyService = safetyService;
            _sysService = sysService;
        }

        [CoreCat]
        public ResponseData<Sys_UserData> Login(string userName, string password)
        {
            var sysUser = _sysUserService.Get(x => x.UserName == userName);
            return this.DoLogin(sysUser, password);
        }


        public ResponseData<Sys_UserData> AutoLogin(int userId)
        {
            var sysUser = _sysUserService.Get(x => x.Id == userId);
            return this.DoLogin(sysUser, null);
        }

        [CoreCat]
        private ResponseData<Sys_UserData> DoLogin(Sys_User sysUser, string pwd = null)
        {
            if (sysUser == null)
                return ResponseData<Sys_UserData>.Failtrue("未注册用户信息");
            var safety = _safetyService.CheckSafety(sysUser.Id);
            if (!safety.Item1)
                return ResponseData<Sys_UserData>.Failtrue(safety.Item2);
            if (sysUser.IsDelete == (int)GlobalEnum.YN.Yes)
                return ResponseData<Sys_UserData>.Failtrue("用户信息已过期");
            if (sysUser.Status == (int)GlobalEnum.SysUserStatus.Freeze)
                return ResponseData<Sys_UserData>.Failtrue("用户已被冻结");

            if (!string.IsNullOrEmpty(pwd))
            {
                if (!sysUser.Pwd.Equals(pwd))
                    return ResponseData<Sys_UserData>.Failtrue("用户名或密码错误");
            }

            var sysUserData = Mapper.Map<Sys_UserData>(sysUser);
            //用户角色
            var userRole = _sysUserRoleService.Select(x => x.IsDelete == (int)GlobalEnum.YN.No && x.UserId == sysUser.Id);
            var roleIds = userRole.Select(x => x.RoleId);
            var role = _sysRoleService.Select(x => roleIds.Contains(x.Id));
            sysUserData.Roles = Mapper.Map<List<Sys_User_RoleData>>(role);
            //主角色
            sysUserData.MainRole = sysUserData.Roles.FirstOrDefault(x => x.Id == sysUser.MainRoleId);

            //角色权限
            var rolePermission = _sysRolePermissionService.Select(x => x.IsDelete == (int)GlobalEnum.YN.No && roleIds.Contains(x.RoleId));
            //权限
            var rolePermissionIds = rolePermission.Select(x => x.PermissionId);
            var permission = _sysPermissionService.Select(x => x.IsDelete == (int)GlobalEnum.YN.No && rolePermissionIds.Contains(x.Id));
            //菜单
            var menuPermission = permission.Where(x => x.ReferType == (int)GlobalEnum.SysPermissionReferType.Menu);
            var menuIds = menuPermission.Select(x => x.ReferId);

            var menu = _sysMenuService.Select(x => menuIds.Contains(x.Id));
            //菜单层级
            sysUserData.Menus = _sysService.LevelInfo(menu).ToList();

            AfterLogin(sysUser, true);
            return ResponseData<Sys_UserData>.Success(sysUserData);
        }

        private void AfterLogin(Sys_User sysUser, bool isComplete)
        {
            sysUser.UpdateTime = DateTime.Now;

            if (isComplete)
                sysUser.LoginCount += 1;
            else
                sysUser.ErrorCount += 1;

            if (!_sysUserService.Update(sysUser))
            {
                //todo:记录错误日志
            }

            _safetyService.SafetyLog(sysUser.Id, isComplete);
        }
    }
}
